package pe.com.cotelasa.common.printer;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.print.attribute.standard.MediaSizeName;

import pe.com.cotelasa.scp.dominio.common.util.UtilitarioFecha;

@SuppressWarnings({"unchecked","unused","rawtypes"})
public class PrinterService {

	private char activateBold[] = { (char) 27, 'E' };
	
	private char deactivateBold[] = { (char) 27, 'F' };

	private char activateCondensed[] = { (char) 15 };
	
	private char deactivateCondensed[] = { (char) 18 };

	private char activateUnderline[] = { (char) 27, (char) 45, (char) 49 };
	
	private char deactivateUnderline[] = { (char) 27, (char) 45, (char) 48 };

	private char activateDoubleWidthMode[] = { (char) 27, (char) 87, (char) 49 };
	
	private char deactivateDoubleWidthMode[] = { (char) 27, (char) 87, (char) 48 };

	private char page10Lines[] = { (char) 27, (char) 67, (char) 10 };
	
	private char page24Lines[] = { (char) 27, (char) 67, (char) 24 };
	
	private char page36Lines[] = { (char) 27, (char) 67, (char) 36 };
	
	private char page66Lines[] = { (char) 27, (char) 67, (char) 66 };

	private char pageBreak[] = { (char) 12 };

	private char carriageReturn[] = { (char) 13 };

	private PrintStream ps;
	
	private char pageSize[];
	
	private int linesPerPage = 0;
	
	private int printArea = 0;

	private int actualLine = 0;

	private int headerSize = 0;
	
	private int footerSize = 0;

	private String devicePort = "";

	private boolean includeDatePage = false;
	
	private String reportDate = "";
	
	private int pageNumber = 1;

	private ArrayList arrayHeader = new ArrayList();
	
	private boolean settingHeader = false;
	
	private ArrayList arrayFooter = new ArrayList();
	
	private boolean settingFooter = false;

	private String programName = "";


	public PrinterService(int pLinesPerPage, String pDevicePort,
			boolean pIncludeDatePage) {
		linesPerPage = pLinesPerPage;
		printArea = linesPerPage - 4;
		devicePort = pDevicePort;
		includeDatePage = pIncludeDatePage;
		switch (linesPerPage) {
		case (10): {
			pageSize = page10Lines;
			break;
		}
		case (24): {
			pageSize = page24Lines;
			break;
		}
		case (36): {
			pageSize = page36Lines;
			break;
		}
		case (66): {
			pageSize = page66Lines;
			break;
		}              
		default:
			pageSize = page66Lines;
		}
	}

	public boolean startPrintService() {
		boolean valorRetorno = false;
		try {
			FileOutputStream fos = new FileOutputStream(devicePort);
			ps = new PrintStream(fos);
			ps.print(deactivateCondensed);
			//ps.print(MediaSizeName.ISO_A4);
                        ps.print(pageSize);
			ps.print(carriageReturn);
			ps.println(" ");

			ps.print(carriageReturn);
			if (includeDatePage) {
				printArea -= 3;
				reportDate = UtilitarioFecha.obtenerFechaActual();
				printPageNumber();
			}
			valorRetorno = true;
		} catch (FileNotFoundException errFileNotFound) {
			errFileNotFound.printStackTrace();
		} catch (Exception errException) {
			errException.printStackTrace();
		}
		return valorRetorno;
	}

	
	public void endPrintService() {
		for (int i = 1; i < getRemainingLines() + 2; i++) {
			ps.println(" ");
			ps.print(carriageReturn);
		}
		printArray(arrayFooter);
		if (includeDatePage)
			printDatePage();
		ps.print("\f");
		ps.flush();
		ps.close();
	}

	public void setStartHeader() {
		settingHeader = true;
	}

	public void setEndHeader() {
		settingHeader = false;
		headerSize += actualLine;
		actualLine = 0;
		printArray(arrayHeader);
	}

	public void setStartFooter() {
		settingFooter = true;
	}

	public void setEndFooter() {
		settingFooter = false;
		footerSize += actualLine;
		actualLine = 0;
	}

	public void activateBold() {
		setProperties(activateBold);
	}

	public void deactivateBold() {
		setProperties(deactivateBold);
	}

	public void printBold(String pText, boolean pChangeLine) {
		activateBold();
		printLine(pText, pChangeLine);
		deactivateBold();
	}

	public void activateCondensed() {
		setProperties(activateCondensed);
	}

	public void deactivateCondensed() {
		setProperties(deactivateCondensed);
	}

	public void printCondensed(String pText, boolean pChangeLine) {
		activateCondensed();
		printLine(pText, pChangeLine);
		deactivateCondensed();
	}

	public void activateDoubleWidthMode() {
		setProperties(activateDoubleWidthMode);
	}

	public void deactivateDoubleWidthMode() {
		setProperties(deactivateDoubleWidthMode);
	}

	public void printDoubleWidthMode(String pText, boolean pChangeLine) {
		activateDoubleWidthMode();
		printLine(pText, pChangeLine);
		deactivateDoubleWidthMode();
	}

	public void printLine(String pText, boolean pChangeLine) {
		setPrintLine(pText, pChangeLine);
		if (pChangeLine)
			actualLine += 1;

		if (totalLine() > printArea)
			internalPageBreak(true);
	}

	private void setPrintLine(String pText, boolean pChangeLine) {
		if (settingHeader && pChangeLine)
			arrayHeader.add("1" + pText);
		else if (settingHeader && !pChangeLine)
			arrayHeader.add("0" + pText);
		else if (settingFooter && pChangeLine)
			arrayFooter.add("1" + pText);
		else if (settingFooter && !pChangeLine)
			arrayFooter.add("0" + pText);
		else if (pChangeLine) {
			ps.println(pText);
			//ps.print(carriageReturn);
		} else
			ps.print(pText);
	}

	public int getRemainingLines() {
		return printArea - totalLine();
	}

	public void printBlankLine(int pLineNumber) {
		for (int i = 0; i < pLineNumber; i++)
			printLine(" ", true);
	}
        
        public void printBlankLineSinSalto(int pLineNumber) {
		for (int i = 0; i < pLineNumber; i++)
			printLine(" ", false);
	}

	public void pageBreak() {
		internalPageBreak(false);
	}

	public void setProgramName(String pProgramName) {
		programName = pProgramName;
	}

	private void setProperties(char[] pProperties) {
		if (settingHeader)
			arrayHeader.add(pProperties);
		else if (settingFooter)
			arrayFooter.add(pProperties);
		else
			ps.print(pProperties);
	}

	private void printArray(ArrayList pPrintArray) {
		String textToPrint = "";
		for (int i = 0; i < pPrintArray.size(); i++) {
			if (pPrintArray.get(i) instanceof String) {
				textToPrint = ((String) pPrintArray.get(i)).trim();
				if (textToPrint.substring(0, 1).equalsIgnoreCase("1")) {
					ps.println(textToPrint.substring(1, textToPrint.length()));
					ps.print(carriageReturn);
				} else
					ps.print(textToPrint.substring(1, textToPrint.length()));
			} else
				ps.print((char[]) pPrintArray.get(i));
		}
	}

	private void printPageNumber() {
		if (!includeDatePage)
			return;
		String blanks = "";
		for (int i=0; i<74; i++) blanks += " ";
		ps.println(blanks + "Pag. " + pageNumber);
		ps.print(carriageReturn);
		pageNumber += 1;
	}

	private void printDatePage() {
		if (!includeDatePage)
			return;
		ps.println("");
		ps.print(carriageReturn);
		ps.println((programName.length() > 0 ? programName + " - " : "")
				+ "Emision : " + reportDate);
		ps.print(carriageReturn);
	}

	private void internalPageBreak(boolean pIsNormalPageBreak) {
		if (!pIsNormalPageBreak) {
			for (int i = 1; i < getRemainingLines() + 2; i++)
				ps.println(" ");
			ps.print(carriageReturn);
		}
		actualLine = 0;
		printArray(arrayFooter);
		printDatePage();
		setProperties(pageBreak);
		if (pageNumber == 2)
			printArea += 1;
		switch (linesPerPage) {
		case (10): {
			printBlankLine(1);
			break;
		}
		case (24): {
			printBlankLine(1);
			break;
		}
		case (36): {
			printBlankLine(1);
			break;
		}
		case (66): {
			printBlankLine(1);
			break;
		}
		default:
			printBlankLine(1);
		}
		printPageNumber();
		printArray(arrayHeader);
	}

	private int totalLine() {
		return headerSize + footerSize + actualLine;
	}

	public boolean startPrintServiceArchivoTexto() {
		boolean valorRetorno = false;
		try {
			FileOutputStream fos = new FileOutputStream(devicePort);

			ps = new PrintStream(fos);
			ps.print(deactivateCondensed);

			if (includeDatePage) {
				printArea -= 3;
				reportDate = UtilitarioFecha.obtenerFechaActual();
				printPageNumber();
			}
			valorRetorno = true;
		} catch (FileNotFoundException errFileNotFound) {
			errFileNotFound.printStackTrace();
		} catch (Exception errException) {
			errException.printStackTrace();
		}
		return valorRetorno;
	}

	public void endPrintServiceArchivoTexto() {
		if (includeDatePage)
			printDatePage();
		ps.print("\f");
		ps.flush();
		ps.close();
	}

	public void printLineSinEspacio(String pText, boolean pChangeLine) {
		setPrintLineSinEspacio(pText, pChangeLine);
		if (pChangeLine)
			actualLine += 1;
		if (totalLine() > printArea)
			internalPageBreak(true);
	}
	
	private void setPrintLineSinEspacio(String pText, boolean pChangeLine) {
		if (settingHeader && pChangeLine)
			arrayHeader.add("1" + pText);
		else if (settingHeader && !pChangeLine)
			arrayHeader.add("0" + pText);
		else if (settingFooter && pChangeLine)
			arrayFooter.add("1" + pText);
		else if (settingFooter && !pChangeLine)
			arrayFooter.add("0" + pText);
		else if (pChangeLine) {
			ps.print(pText);
			ps.print(carriageReturn);
		} else
			ps.print(pText);
	}

	public int getActualLine() {
		return actualLine;
	}

	public void pageBreakArchivo() {
		internalPageBreak(true);
	}

	public String printPageNumberArchivo() {
		return "Folio: " + (pageNumber++);
	}

	public int getPageNumber() {
		return pageNumber;
	}

}
